[LeetCode-1181]使数组严格递增
题目描述
给定两个数组, 计算使得数组A严格递增的操作次数。
一次操作定义为: 选数组B任意一个数, 替换数组A任意一个数。
约定
- arr1数组认为是数组A, 其长度为
n - arr2数组认为是数组B, 其包含不重复的元素个数为
m - 数组下标均从1开始
思路
一些观察:
- 数组B中的重复数是没有用的. 如果使用数组B中的重复数, 要么导致数组A不严格单调递增(操作到了不同位置), 要么导致操作次数增加(操作到了同一位置).
- 数组B的顺序是无所谓的.
问题转化
- 有了上述观察, 我们可以将问题首先进行转化. 首先将数组B中的重复元素去掉, 并对数组B排序, 记为$B’$.
- 这样问题可以转化成: 从数组$A$和数组$B’$(严格单调递增)中找到一条长度为$n$且严格单调递增的路线, 且路线上从
A跳到B'的次数最少

转化后的问题可以使用动态规划来解决
动态规划
- 状态表示:
- $f[i][j][0]$:表示路线走了长度
i, 考虑了数组$B’$的前j个数, 且最后走到数组$A$的i位置上. - $f[i][j][1]$:表示路线走了长度
i, 考虑了数组$B’$的前j个数, 且最后走到数组$B’$的j位置上.
- $f[i][j][0]$:表示路线走了长度
- 状态计算:
- 根据定义首先有: $f[i][j][0]$ = $f[i][j - 1][0]$
- 若$A[i] > A[i - 1]$, 则有$f[i][j][0]$ = $f[i - 1][j][0]$
- 若 $A[i] > B’[j]$, 则有$f[i][j][0]$ = $f[i - 1][j][1]$
- 对于$f[i][j][1]$:
- 若$B’[j] > A[i - 1]$, 则有$f[i][j][1]$ = $f[i - 1][j - 1][0] + 1$. 表示第
i步从$A$数组的i - 1位置跳到了$B’$的j位置 - 若$B’[j] > B[j - 1]$, 则有$f[i][j][1]$ = $f[i - 1][j - 1][1] + 1$. 表示第
i步从$B’$数组的j - 1位置跳到了$B’$的j位置
- 若$B’[j] > A[i - 1]$, 则有$f[i][j][1]$ = $f[i - 1][j - 1][0] + 1$. 表示第
- 根据定义首先有: $f[i][j][0]$ = $f[i][j - 1][0]$
- 状态表示:
最后的答案
- 若最后一步在$A$数组上, 则答案为$f[n][m][0]$.
- 若最后一步在$B’$数组上, 枚举$f[n][j][1]$, 其中$j\in[0, m)$.
Code
1 | const int N = 2010, INF = 0x3f3f3f3f; |
复杂度分析
- 时间复杂度$O(n^2)$
- 空间复杂度$O(n^2)$
欢迎讨论指正
[LeetCode-1181]使数组严格递增
https://csjsss.github.io/2021/11/11/algo/LeetCode/每日一题/[LeetCode-1181]使数组严格递增/

